package org.hawk.gwt.ppc.reflect;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import org.hawk.gwt.ppc.Configuration;
import org.hawk.gwt.ppc.GWTModule;
import org.hawk.gwt.ppc.javacc.JavaParserTreeConstants;
import org.hawk.gwt.ppc.javacc.JavaScanner;
import org.hawk.gwt.ppc.javacc.ParseException;
import org.hawk.gwt.ppc.scanner.ProcessingUnit;
import org.hawk.gwt.ppc.scanner.Processor;
import org.hawk.gwt.ppc.scanner.Token;
import org.hawk.gwt.ppc.scanner.TokenChain;
import org.hawk.gwt.ppc.utils.IO;

/**
 * Represents simple preprocessor to replace the package declaration for
 * <code>org.hawk.gwt.ppc.reflect.emul.java.lang</code> package classes. This
 * was done retain the ability to run simple JUnit tests on java code.
 * 
 * @author alex.bereznevatiy@gmail.com
 */
public class LangPreprocessor implements ProcessingUnit, Processor {
	private static final String PACKAGE = "org.hawk.gwt.ppc.reflect";

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hawk.gwt.ppc.scanner.Preprocessor#configure(org.hawk.gwt.ppc.
	 * Configuration, org.hawk.gwt.ppc.javacc.JavaScanner)
	 */
	public void configure(Configuration config, JavaScanner scanner) {
		scanner.addProcessor(JavaParserTreeConstants.JJTPACKAGEDECLARATION,
				this);
		scanner.addProcessor(JavaParserTreeConstants.JJTIMPORTDECLARATION, this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.hawk.gwt.ppc.scanner.Preprocessor#processModule(org.hawk.gwt.ppc.
	 * GWTModule)
	 */
	public void processModule(GWTModule module) {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.hawk.gwt.ppc.scanner.Preprocessor#processEntryPoint(java.lang.String,
	 * java.io.Reader, java.io.Writer)
	 */
	public void processEntryPoint(String entryPoint, Reader reader,
			Writer writer) throws IOException {
		IO.flow(reader, writer);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.hawk.gwt.ppc.scanner.Preprocessor#acceptResource(java.lang.String)
	 */
	public boolean acceptResource(String resource) {
		return resource.startsWith(PACKAGE);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.hawk.gwt.ppc.scanner.Processor#visitStart(org.hawk.gwt.ppc.scanner
	 * .TokenChain, int)
	 */
	public void visitStart(TokenChain<? extends Token> iterator, int kind) {
	}

	public void visitEnd(TokenChain<? extends Token> iterator, int kind)
			throws IOException, ParseException {
		if (kind != JavaParserTreeConstants.JJTPACKAGEDECLARATION
				&& kind != JavaParserTreeConstants.JJTIMPORTDECLARATION) {
			return;
		}
		processLangPackage(iterator);
	}

	private void processLangPackage(TokenChain<? extends Token> iterator) {
		boolean removeFlag = false;
		do {
			if (!removeFlag && iterator.current().getToken().equals("emul")) {
				iterator.next();
				removeFlag = true;
			}
			if (removeFlag) {
				iterator.current().setToken("");
			}
			String prev = iterator.previous().getToken();
			String raw = iterator.current().getRawToken();
			if (prev.equals("package")) {
				if (removeFlag)
					iterator.current().setToken("package ");
				return;
			}
			if (prev.equals("import")) {
				if (removeFlag)
					iterator.current().setToken(
							raw.replace("import", "import "));
				return;
			}
		} while (iterator.hasPrevious());
	}
}
